<!DOCTYPE html>
<html >

<head>

  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据</title>
  <meta name="description" content="第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据">
  <meta name="generator" content="bookdown  and GitBook 2.6.7">

  <meta property="og:title" content="第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据" />
  <meta property="og:type" content="book" />
  
  <meta property="og:image" content="images/coverpage.png" />
  <meta property="og:description" content="第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据" />
  <meta name="github-repo" content="zhujiedong/tidydevanalysis" />

  <meta name="twitter:card" content="summary" />
  <meta name="twitter:title" content="第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据" />
  
  <meta name="twitter:description" content="第 5 章 数据的转换 | 使用 tidyverse 的方式分析仪器测量的数据" />
  <meta name="twitter:image" content="images/coverpage.png" />

<meta name="author" content="祝介东    北京力高泰科技有限公司">


<meta name="date" content="2019-03-21">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  
  
<link rel="prev" href="rioexport.html">
<link rel="next" href="dplyr.html">
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />









<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(title);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>

<link rel="stylesheet" href="css\style.css" type="text/css" />
</head>

<body>



  <div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">

    <div class="book-summary">
      <nav role="navigation">

<ul class="summary">
<li><a href="./">R 软件与仪器数据分析</a></li>

<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>欢迎</a></li>
<li class="chapter" data-level="" data-path="frontmatter.html"><a href="frontmatter.html"><i class="fa fa-check"></i>前言</a></li>
<li class="chapter" data-level="" data-path="author.html"><a href="author.html"><i class="fa fa-check"></i>关于作者</a></li>
<li class="chapter" data-level="" data-path="copyright.html"><a href="copyright.html"><i class="fa fa-check"></i>版权</a></li>
<li class="part"><span><b>I Part I</b></span></li>
<li class="chapter" data-level="1" data-path="origin-tidyverse.html"><a href="origin-tidyverse.html"><i class="fa fa-check"></i><b>1</b> tidyverse 的起源</a><ul>
<li class="chapter" data-level="1.1" data-path="origin-tidyverse.html"><a href="origin-tidyverse.html#tidyworkflow"><i class="fa fa-check"></i><b>1.1</b> tidyverse 的流程</a></li>
</ul></li>
<li class="chapter" data-level="2" data-path="prerequisites.html"><a href="prerequisites.html"><i class="fa fa-check"></i><b>2</b> 准备工作</a></li>
<li class="part"><span><b>II Part II</b></span></li>
<li class="chapter" data-level="3" data-path="readr.html"><a href="readr.html"><i class="fa fa-check"></i><b>3</b> tidyverse 数据格式</a><ul>
<li class="chapter" data-level="3.1" data-path="readr.html"><a href="readr.html#attridiff"><i class="fa fa-check"></i><b>3.1</b> 属性的差别</a></li>
<li class="chapter" data-level="3.2" data-path="readr.html"><a href="readr.html#parse-str"><i class="fa fa-check"></i><b>3.2</b> 数据类型的解析</a><ul>
<li class="chapter" data-level="3.2.1" data-path="readr.html"><a href="readr.html#factor-str"><i class="fa fa-check"></i><b>3.2.1</b> 因子类型</a></li>
<li class="chapter" data-level="3.2.2" data-path="readr.html"><a href="readr.html#datetime"><i class="fa fa-check"></i><b>3.2.2</b> 时间与日期</a></li>
</ul></li>
<li class="chapter" data-level="3.3" data-path="readr.html"><a href="readr.html#julian-day-"><i class="fa fa-check"></i><b>3.3</b> Julian day 的转换</a></li>
<li class="chapter" data-level="3.4" data-path="readr.html"><a href="readr.html#package-"><i class="fa fa-check"></i><b>3.4</b> 常用 package 介绍</a></li>
<li class="chapter" data-level="3.5" data-path="readr.html"><a href="readr.html#corereadr"><i class="fa fa-check"></i><b>3.5</b> readr 包核心函数</a></li>
<li class="chapter" data-level="3.6" data-path="readr.html"><a href="readr.html#corereadxl"><i class="fa fa-check"></i><b>3.6</b> readxl</a></li>
<li class="chapter" data-level="3.7" data-path="readr.html"><a href="readr.html#featherrds"><i class="fa fa-check"></i><b>3.7</b> 二进制文件</a></li>
<li class="chapter" data-level="3.8" data-path="readr.html"><a href="readr.html#rio"><i class="fa fa-check"></i><b>3.8</b> <code>rio</code>–万能的瑞士军刀</a><ul>
<li class="chapter" data-level="3.8.1" data-path="readr.html"><a href="readr.html#insrio"><i class="fa fa-check"></i><b>3.8.1</b> 安装</a></li>
<li class="chapter" data-level="3.8.2" data-path="readr.html"><a href="readr.html#imp-rio"><i class="fa fa-check"></i><b>3.8.2</b> 数据的读取</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="4" data-path="rioexport.html"><a href="rioexport.html"><i class="fa fa-check"></i><b>4</b> 使用 <code>rio</code> 导出数据</a><ul>
<li class="chapter" data-level="4.1" data-path="rioexport.html"><a href="rioexport.html#rioconvert"><i class="fa fa-check"></i><b>4.1</b> 数据的转换</a></li>
</ul></li>
<li class="part"><span><b>III Part III</b></span></li>
<li class="chapter" data-level="5" data-path="tidydata.html"><a href="tidydata.html"><i class="fa fa-check"></i><b>5</b> 数据的转换</a><ul>
<li class="chapter" data-level="5.1" data-path="tidydata.html"><a href="tidydata.html#tidyr"><i class="fa fa-check"></i><b>5.1</b> 使用 <code>tidyr</code> 清洁数据</a><ul>
<li class="chapter" data-level="5.1.1" data-path="tidydata.html"><a href="tidydata.html#gather"><i class="fa fa-check"></i><b>5.1.1</b> <code>gather</code> 用于合并数据集</a></li>
<li class="chapter" data-level="5.1.2" data-path="tidydata.html"><a href="tidydata.html#spread"><i class="fa fa-check"></i><b>5.1.2</b> <code>spread</code> 用于展开数据集</a></li>
<li class="chapter" data-level="5.1.3" data-path="tidydata.html"><a href="tidydata.html#separate"><i class="fa fa-check"></i><b>5.1.3</b> <code>separate</code> 用于单列数据的分离</a></li>
<li class="chapter" data-level="5.1.4" data-path="tidydata.html"><a href="tidydata.html#unite"><i class="fa fa-check"></i><b>5.1.4</b> <code>unite</code> 整合不同的列</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="6" data-path="dplyr.html"><a href="dplyr.html"><i class="fa fa-check"></i><b>6</b> <code>dplyr</code>–数据操作的语法</a></li>
<li class="chapter" data-level="7" data-path="todo.html"><a href="todo.html"><i class="fa fa-check"></i><b>7</b> todo</a><ul>
<li class="chapter" data-level="7.1" data-path="todo.html"><a href="todo.html#data-transformation"><i class="fa fa-check"></i><b>7.1</b> data transformation</a></li>
<li class="chapter" data-level="7.2" data-path="todo.html"><a href="todo.html#data-visulization"><i class="fa fa-check"></i><b>7.2</b> data visulization</a></li>
<li class="chapter" data-level="7.3" data-path="todo.html"><a href="todo.html#model-r"><i class="fa fa-check"></i><b>7.3</b> model r</a></li>
<li class="chapter" data-level="7.4" data-path="todo.html"><a href="todo.html#public"><i class="fa fa-check"></i><b>7.4</b> public</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>参考文献</a></li>
<li class="divider"></li>
<li><a href="https://bookdown.org" target="blank">由 bookdown 驱动</a></li>

</ul>

      </nav>
    </div>

    <div class="book-body">
      <div class="body-inner">
        <div class="book-header" role="navigation">
          <h1>
            <i class="fa fa-circle-o-notch fa-spin"></i><a href="./">使用 tidyverse 的方式分析仪器测量的数据</a>
          </h1>
        </div>

        <div class="page-wrapper" tabindex="-1" role="main">
          <div class="page-inner">

            <section class="normal" id="section-">
<div id="tidydata" class="section level1">
<h1><span class="header-section-number">第 5 章</span> 数据的转换</h1>
<p>首先，tidyverse 数据的核心为 “tidy data”，所有软件都是要根据这个核心来进行数据处理，或者是将非 “tidy data” 转换为 “tidy data”，那么什么是 “tidy data” 呢？ <span class="citation">Wickham (<a href="#ref-jsstidy">2014</a>)</span> 对其进行了详细的阐述，核心观点可以参考图 <a href="tidydata.html#fig:tidydata">5.1</a>:</p>
<div class="figure"><span id="fig:tidydata"></span>
<img src="https://d33wubrfki0l68.cloudfront.net/6f1ddb544fc5c69a2478e444ab8112fb0eea23f8/91adc/images/tidy-1.png" alt="图解 tidy data "  />
<p class="caption">
图 5.1: 图解 tidy data
</p>
</div>
<p>用三句话概括：</p>
<ul>
<li>每个变量必须单独成列。</li>
<li>每个观察值必须单独成行。</li>
<li>每个数值必须具有单独的单元格。</li>
</ul>
<p>拿整理好的光合数据举例，每个测量参数，如 A，Ci 等，都具有单独的列，每个 obs 列代表了一次测量，每次测量都是单独的一行，对应了各个测量的参数，每个单元格只有一个数值，不存在这样表示的单元格, 例如 表头为 “A/Ci”，观测值为 “12/200”。</p>
<p>这样做的优势也是显而易见的：</p>
<ul>
<li><p>所有数据的存储结构都是一致的，我们调用非常方便，拿到数据后不需要思考，直接调用即可。最重要的，他是 “tidyverse” 以及多数的软件包所支持的格式。</p></li>
<li><p>R 是原生的支持向量化操作的软件，将每个变量单独成列，也就是每个变量都是同一数据类型，本质上就是向量，这样 R 内置的函数都支持这些类型的数据的处理。</p></li>
</ul>
<div id="tidyr" class="section level2">
<h2><span class="header-section-number">5.1</span> 使用 <code>tidyr</code> 清洁数据</h2>
<p><code>tidyr</code> 核心函数有三个，分别是 <code>gather()</code>, <code>separate()</code> 以及 <code>spread()</code>，主要目的是对数据进行拆分，合并等清洁操作，单独使用是可行的，但最好结合 <code>dplyr</code> 来进行操作，会大大的解放我们的生产力，这里我们先不对 <code>dplyr</code> 的内容进行介绍，后面 <a href="dplyr.html#dplyr">6</a> 再详细介绍。</p>
<div id="gather" class="section level3">
<h3><span class="header-section-number">5.1.1</span> <code>gather</code> 用于合并数据集</h3>
<p><code>gather</code> 用于将多列数据合并为一列，视觉上看上去数据由宽变长，这是它的一个特征，例如我有这样两个数据，按月份测量了光合速率 (表 <a href="tidydata.html#tab:messa">5.1</a>) 和蒸腾速率 (表 <a href="tidydata.html#tab:messe">5.2</a>)：</p>
<pre class="sourceCode r"><code class="sourceCode r">messa &lt;-<span class="st"> </span><span class="kw">readRDS</span>(<span class="st">&quot;./data/messa.RDS&quot;</span>)
messe &lt;-<span class="st"> </span><span class="kw">readRDS</span>(<span class="st">&quot;./data/messe.RDS&quot;</span>)</code></pre>
<table>
<caption><span id="tab:messa">表 5.1: </span>5-6月光合数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">May</th>
<th align="center">Jun</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">20.61053</td>
<td align="center">30.90637</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">20.18174</td>
<td align="center">29.39688</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">17.94135</td>
<td align="center">14.65996</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">17.81593</td>
<td align="center">14.06745</td>
</tr>
</tbody>
</table>
<table>
<caption><span id="tab:messe">表 5.2: </span>5-6月蒸腾数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">May</th>
<th align="center">Jun</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">0.0303354</td>
<td align="center">0.0501694</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">0.0299274</td>
<td align="center">0.0501956</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">0.0348524</td>
<td align="center">0.0039654</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">0.0350129</td>
<td align="center">0.0039123</td>
</tr>
</tbody>
</table>
<p>这个数据记录的最大问题是，后面两列都是同一变量，按照原则，二者应为同一列，而不是分为两列，需要合并，<code>tidyr</code> 都是 <code>tidyverse</code> 的核心包，此时我们只用 <code>tidyr</code>：</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(tidyr)

tidya_data &lt;-<span class="st"> </span>messa <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">gather</span>(May, Jun, <span class="dt">key =</span> <span class="st">&quot;month&quot;</span>, <span class="dt">value =</span> <span class="st">&quot;A&quot;</span>)

tidye_data &lt;-<span class="st"> </span>messe <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">gather</span>(May, Jun, <span class="dt">key =</span> <span class="st">&quot;month&quot;</span>, <span class="dt">value =</span> <span class="st">&quot;E&quot;</span>)</code></pre>
<p>清洁后数据分别见表 <a href="tidydata.html#tab:messa">5.1</a> 和表 <a href="tidydata.html#tab:messe">5.2</a>。</p>
<table>
<caption><span id="tab:tidya">表 5.3: </span>清洁后5-6月光合数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">month</th>
<th align="center">A</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">20.61053</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">20.18174</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">17.94135</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">17.81593</td>
</tr>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">30.90637</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">29.39688</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">14.65996</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">14.06745</td>
</tr>
</tbody>
</table>
<table>
<caption><span id="tab:tidye">表 5.4: </span>清洁后5-6月蒸腾数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">month</th>
<th align="center">E</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">0.0303354</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">0.0299274</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">0.0348524</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">0.0350129</td>
</tr>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">0.0501694</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">0.0501956</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">0.0039654</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">0.0039123</td>
</tr>
</tbody>
</table>
<p>先简单介绍一下 <code>gather</code> 怎么实现上述清洁：key 指的是我们原来数据中表头的名字，value 指的是原来数据中的测量值，在本例中 key 为我们不同月份，value 是我们每月测量的光合速率的值。
如果你留意到了 “%&gt;”，那么恭喜你，你注意到了 <code>tidyverse</code> 软件包所支持的一种非常直观的语法，我们称之为管道（pipes），它来自 <code>magrittr</code>，跟 linux 语法中的管道意思类似，可以很方便的讲我们符号之前的变量传递给后面的变量，例如：</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(magrittr)</code></pre>
<pre><code>## 
## Attaching package: &#39;magrittr&#39;</code></pre>
<pre><code>## The following object is masked from &#39;package:purrr&#39;:
## 
##     set_names</code></pre>
<pre><code>## The following object is masked from &#39;package:tidyr&#39;:
## 
##     extract</code></pre>
<pre class="sourceCode r"><code class="sourceCode r">x =<span class="st"> </span><span class="dv">1</span><span class="op">:</span><span class="dv">1000</span>
z =<span class="st"> </span><span class="kw">sum</span>((<span class="kw">mean</span>(<span class="kw">diff</span>(x))), x)
z</code></pre>
<pre><code>## [1] 500501</code></pre>
<pre class="sourceCode r"><code class="sourceCode r">z &lt;-<span class="st"> </span>x <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">diff</span>() <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">mean</span>() <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">sum</span>(x)
z</code></pre>
<pre><code>## [1] 500501</code></pre>
<p>当然，在此处的优势不是特别明显,但单从视觉上来看，无疑使用管道符号更为直观，当然，当你知道可以通过 ctr+shift+M 可以直接输入 %&gt;% 时，无疑你会从痛苦和疑惑中解脱。其他优势我们不介绍，后面使用时会很清晰的看到。</p>
</div>
<div id="spread" class="section level3">
<h3><span class="header-section-number">5.1.2</span> <code>spread</code> 用于展开数据集</h3>
<p>与 <code>gather</code> 相对应，<code>spread</code> 用于将数据展开，例如我有如表 <a href="tidydata.html#tab:messc">5.5</a> 的数据 messc：</p>
<pre class="sourceCode r"><code class="sourceCode r">messc &lt;-<span class="st"> </span><span class="kw">readRDS</span>(<span class="st">&quot;./data/messc.RDS&quot;</span>)</code></pre>
<table>
<caption><span id="tab:messc">表 5.5: </span>5-6月光合蒸腾数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">month</th>
<th align="center">type</th>
<th align="center">measure</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">A</td>
<td align="center">20.3393647</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">E</td>
<td align="center">0.0299543</td>
</tr>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">A</td>
<td align="center">20.0542329</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">E</td>
<td align="center">0.0398827</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">A</td>
<td align="center">30.2665086</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">E</td>
<td align="center">0.0498585</td>
</tr>
<tr class="odd">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">A</td>
<td align="center">30.1753295</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">E</td>
<td align="center">0.0549767</td>
</tr>
</tbody>
</table>
<p>很明显，光合和蒸腾属于两个变量，不应放在一起，<code>spread</code> 使用方式同 <code>gather</code> 类似，其中 key 指的是 type，value 只的是测量值 measure：</p>
<pre class="sourceCode r"><code class="sourceCode r">tidyc_data &lt;-<span class="st"> </span>messc <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">spread</span>(<span class="dt">key=</span>type,<span class="dt">value =</span> measure)</code></pre>
<table>
<caption>(#tab:tidyc_data)清洁后的5-6月光合蒸腾数据</caption>
<thead>
<tr class="header">
<th align="center">species</th>
<th align="center">month</th>
<th align="center">A</th>
<th align="center">E</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">corn</td>
<td align="center">Jun</td>
<td align="center">30.17533</td>
<td align="center">0.0549767</td>
</tr>
<tr class="even">
<td align="center">corn</td>
<td align="center">May</td>
<td align="center">30.26651</td>
<td align="center">0.0498585</td>
</tr>
<tr class="odd">
<td align="center">wheat</td>
<td align="center">Jun</td>
<td align="center">20.05423</td>
<td align="center">0.0398827</td>
</tr>
<tr class="even">
<td align="center">wheat</td>
<td align="center">May</td>
<td align="center">20.33936</td>
<td align="center">0.0299543</td>
</tr>
</tbody>
</table>
</div>
<div id="separate" class="section level3">
<h3><span class="header-section-number">5.1.3</span> <code>separate</code> 用于单列数据的分离</h3>
<p>对于一些手动记录的调查数据，通常存在的问题就是本该分成两列的数据放在了一列，用了一些符号和空格隔开，例如表 <a href="tidydata.html#tab:srsepc">5.6</a> 数据</p>
<pre class="sourceCode r"><code class="sourceCode r">crsep &lt;-<span class="st"> </span><span class="kw">readRDS</span>(<span class="st">&quot;./data/crseparate.RDS&quot;</span>)</code></pre>
<table>
<caption><span id="tab:srsepc">表 5.6: </span>未分列的数据</caption>
<thead>
<tr class="header">
<th align="center">date</th>
<th align="center">volt_ptemp</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">2018/5/19 11:00</td>
<td align="center">14/26</td>
</tr>
<tr class="even">
<td align="center">2018/5/19 11:30</td>
<td align="center">14/27</td>
</tr>
<tr class="odd">
<td align="center">2018/5/19 12:00</td>
<td align="center">14/28</td>
</tr>
<tr class="even">
<td align="center">2018/5/19 12:30</td>
<td align="center">14/28</td>
</tr>
<tr class="odd">
<td align="center">2018/5/19 13:00</td>
<td align="center">14/28</td>
</tr>
<tr class="even">
<td align="center">2018/5/19 13:30</td>
<td align="center">14/28</td>
</tr>
</tbody>
</table>
<p>时间和日期如果是分开的，对于我们处理起来比较方便，机箱的电池电压和温度同样，不应在一列：</p>
<pre class="sourceCode r"><code class="sourceCode r">crnor &lt;-<span class="st"> </span>crsep <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">separate</span>(date, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;date&quot;</span>, <span class="st">&quot;time&quot;</span>), <span class="dt">sep =</span> <span class="st">&quot; &quot;</span>) <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">separate</span>(volt_ptemp, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;batt_v&quot;</span>, <span class="st">&quot;ptemp&quot;</span>))</code></pre>
<p>注意，我们只有第一次分列使用了 <code>sep=</code> 参数，原因是 <code>separate</code> 默认使用非字母数字分隔。日期和时间中存在了非字母数字的符号，所以我们制定使用空格分列，而对于后面的数据，没有其他非字母数字的符号存在，整理后数据如 <a href="tidydata.html#tab:crnor">5.7</a> 所示。</p>
<table>
<caption><span id="tab:crnor">表 5.7: </span>分列处理后的数据</caption>
<thead>
<tr class="header">
<th align="center">date</th>
<th align="center">time</th>
<th align="center">batt_v</th>
<th align="center">ptemp</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">2018/5/19</td>
<td align="center">11:00</td>
<td align="center">14</td>
<td align="center">26</td>
</tr>
<tr class="even">
<td align="center">2018/5/19</td>
<td align="center">11:30</td>
<td align="center">14</td>
<td align="center">27</td>
</tr>
<tr class="odd">
<td align="center">2018/5/19</td>
<td align="center">12:00</td>
<td align="center">14</td>
<td align="center">28</td>
</tr>
<tr class="even">
<td align="center">2018/5/19</td>
<td align="center">12:30</td>
<td align="center">14</td>
<td align="center">28</td>
</tr>
<tr class="odd">
<td align="center">2018/5/19</td>
<td align="center">13:00</td>
<td align="center">14</td>
<td align="center">28</td>
</tr>
<tr class="even">
<td align="center">2018/5/19</td>
<td align="center">13:30</td>
<td align="center">14</td>
<td align="center">28</td>
</tr>
</tbody>
</table>
<p>此时我们需要注意的是，如果我们看一下整理好后的数据类型：</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">str</span>(crnor)</code></pre>
<pre><code>## &#39;data.frame&#39;:    15 obs. of  4 variables:
##  $ date  : chr  &quot;2018/5/19&quot; &quot;2018/5/19&quot; &quot;2018/5/19&quot; &quot;2018/5/19&quot; ...
##  $ time  : chr  &quot;11:00&quot; &quot;11:30&quot; &quot;12:00&quot; &quot;12:30&quot; ...
##  $ batt_v: chr  &quot;14&quot; &quot;14&quot; &quot;14&quot; &quot;14&quot; ...
##  $ ptemp : chr  &quot;26&quot; &quot;27&quot; &quot;28&quot; &quot;28&quot; ...</code></pre>
<p>我们发现这些类型的识别是不符合实际的，但我们可以使用 <code>separate</code> 方便的进行转换：</p>
<pre class="sourceCode r"><code class="sourceCode r">crnor &lt;-<span class="st"> </span>crsep <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">separate</span>(date, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;date&quot;</span>, <span class="st">&quot;time&quot;</span>), <span class="dt">sep =</span> <span class="st">&quot; &quot;</span>, <span class="dt">convert =</span> <span class="ot">TRUE</span>) <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">separate</span>(volt_ptemp, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;batt_v&quot;</span>, <span class="st">&quot;ptemp&quot;</span>), <span class="dt">convert =</span> <span class="ot">TRUE</span>)
<span class="kw">str</span>(crnor)</code></pre>
<pre><code>## &#39;data.frame&#39;:    15 obs. of  4 variables:
##  $ date  : chr  &quot;2018/5/19&quot; &quot;2018/5/19&quot; &quot;2018/5/19&quot; &quot;2018/5/19&quot; ...
##  $ time  : chr  &quot;11:00&quot; &quot;11:30&quot; &quot;12:00&quot; &quot;12:30&quot; ...
##  $ batt_v: int  14 14 14 14 14 14 14 14 14 14 ...
##  $ ptemp : int  26 27 28 28 28 28 29 30 31 31 ...</code></pre>
<p>时间和日期的格式还是不对，不过这不影响大局，格式转换也不是 <code>tidyr</code> 的所擅长的内容，我们后面介绍 <code>dplyr</code> 时再介绍。</p>
<p>还有就是 <code>sep</code> 除了可以设置字符类型外，还可以设置为整数，这样可以方便的按给定的位数分隔字符，例如下面的时间日期写法，如果放在一列，是很不方便的，但它没有分隔符号：</p>
<pre class="sourceCode r"><code class="sourceCode r">messdt &lt;-<span class="st"> </span>tibble<span class="op">::</span><span class="kw">tibble</span>(<span class="dt">dt=</span><span class="kw">c</span>(<span class="st">&quot;198508181311&quot;</span>, <span class="st">&quot;198609191412&quot;</span>, <span class="st">&quot;198710101513&quot;</span> ))
messdt <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">separate</span>(dt, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;date&quot;</span>, <span class="st">&quot;time&quot;</span>), <span class="dt">sep =</span> <span class="st">&quot;8&quot;</span>, <span class="dt">convert =</span> <span class="ot">TRUE</span>)</code></pre>
<pre><code>## Warning: Expected 2 pieces. Additional pieces discarded in 1 rows [1].</code></pre>
<pre><code>## # A tibble: 3 x 2
##    date      time
##   &lt;int&gt;     &lt;int&gt;
## 1    19        50
## 2    19 609191412
## 3    19 710101513</code></pre>
<pre class="sourceCode r"><code class="sourceCode r">messdt <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">separate</span>(dt, <span class="dt">into =</span> <span class="kw">c</span>(<span class="st">&quot;date&quot;</span>, <span class="st">&quot;time&quot;</span>), <span class="dt">sep =</span> <span class="dv">8</span>, <span class="dt">convert =</span> <span class="ot">TRUE</span>)</code></pre>
<pre><code>## # A tibble: 3 x 2
##       date  time
##      &lt;int&gt; &lt;int&gt;
## 1 19850818  1311
## 2 19860919  1412
## 3 19871010  1513</code></pre>
<p>上面的例子告诉我们，使用 <code>sep</code> 分隔数据时，千万注意利用位置分列时，不要加引号，因为它把 “8” 当作了分隔符号。</p>
</div>
<div id="unite" class="section level3">
<h3><span class="header-section-number">5.1.4</span> <code>unite</code> 整合不同的列</h3>
<p><code>unite</code> 作用和 <code>separate</code></p>
<p>恰恰相反，在实际应用过程中不是很常见，但有句话说得好，“书到用时方恨少”，类似的，函数到用时，如果没有，也会给我们带来额外的工作量，例如我有三个小区，每个小区测量三个植株，每个植株测量三个叶片的光合速率，如表 <a href="tidydata.html#tab:sampleid">5.8</a> 所示：</p>
<pre class="sourceCode r"><code class="sourceCode r">sampleid &lt;-<span class="st"> </span><span class="kw">data.frame</span>(
  <span class="dt">plot =</span> <span class="kw">rep</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">3</span>, <span class="dt">each =</span> <span class="dv">3</span>, <span class="dt">times =</span> <span class="dv">3</span> ),
  <span class="dt">plant =</span> <span class="kw">rep</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">3</span>, <span class="dt">each =</span> <span class="dv">9</span>),
  <span class="dt">leaf =</span> <span class="kw">rep</span>(<span class="dv">1</span><span class="op">:</span><span class="dv">3</span>, <span class="dv">9</span>),
  <span class="dt">A =</span> <span class="kw">rnorm</span>(<span class="dv">27</span>, <span class="dv">20</span>, <span class="dv">2</span> )
)</code></pre>
<table>
<caption><span id="tab:sampleid">表 5.8: </span>整合前数据的样式（未完全显示）</caption>
<thead>
<tr class="header">
<th align="center">plot</th>
<th align="center">plant</th>
<th align="center">leaf</th>
<th align="center">A</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">1</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="center">18.75036</td>
</tr>
<tr class="even">
<td align="center">1</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">21.68582</td>
</tr>
<tr class="odd">
<td align="center">1</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="center">20.34216</td>
</tr>
<tr class="even">
<td align="center">2</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="center">21.22866</td>
</tr>
<tr class="odd">
<td align="center">2</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">18.51974</td>
</tr>
<tr class="even">
<td align="center">2</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="center">21.05227</td>
</tr>
</tbody>
</table>
<p>但我们在处理数据的时候，通常只需要一列来区分不同来源的参数，整理完成如表 @ref(tab:tidy_smp) 的样式更符合 tidy data 的要求：</p>
<pre class="sourceCode r"><code class="sourceCode r">tidy_smp &lt;-<span class="st"> </span>sampleid <span class="op">%&gt;%</span><span class="st"> </span>
<span class="st">  </span><span class="kw">unite</span>(treatment, plot, plant, leaf, <span class="dt">sep =</span> <span class="st">&quot;-&quot;</span>)</code></pre>
<table>
<caption>(#tab:tidy_smp)整合三列后数据的样式（未完全显示）</caption>
<thead>
<tr class="header">
<th align="center">treatment</th>
<th align="center">A</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">1-1-1</td>
<td align="center">18.75036</td>
</tr>
<tr class="even">
<td align="center">1-1-2</td>
<td align="center">21.68582</td>
</tr>
<tr class="odd">
<td align="center">1-1-3</td>
<td align="center">20.34216</td>
</tr>
<tr class="even">
<td align="center">2-1-1</td>
<td align="center">21.22866</td>
</tr>
<tr class="odd">
<td align="center">2-1-2</td>
<td align="center">18.51974</td>
</tr>
<tr class="even">
<td align="center">2-1-3</td>
<td align="center">21.05227</td>
</tr>
</tbody>
</table>
<p>整合时可以自定义连接的符号，例如我们做不同处理通常喜欢用上面的显示方式，当然如果特殊需求不喜欢用符号，可以直接设置为 <code>sep = ""</code>。</p>
</div>
</div>
</div>
<h3>参考文献</h3>
<div id="refs" class="references">
<div id="ref-jsstidy">
<p>Wickham, Hadley. 2014. “Tidy Data.” <em>Journal of Statistical Software, Articles</em> 59 (10): 1–23. <a href="https://doi.org/10.18637/jss.v059.i10">https://doi.org/10.18637/jss.v059.i10</a>.</p>
</div>
</div>
            </section>

          </div>
        </div>
      </div>
<a href="rioexport.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="dplyr.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
    </div>
  </div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": true,
"google": false,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "google", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/zhujiedong/tidyphotoanalysis/blob/master/03-1-1-tidy.Rmd",
"text": "缂栬緫"
},
"history": {
"link": null,
"text": null
},
"download": ["bookdown.pdf"],
"toc": {
"collapse": "none"
}
});
});
</script>

</body>

</html>
